home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_01_07
/
1n07066a
< prev
next >
Wrap
Text File
|
1990-09-10
|
5KB
|
163 lines
/*
** Figure 3 - Gameport support functions
**
** This file contains several related functions required to access the
** switch inputs on the gameport in a controlled, debounced fashion.
**
** In order to work correctly, the routine "debounce()" MUST be called
** often as a part of the user program. Debouncing takes place as a
** function of the time interval between successive calls to debounce().
**
** It does not use a specific timebase, although the debounce() function
** could be tied to the user timebase, Int 1Ch.
*/
#include <stdio.h>
#define GAMEPORT 0x201 /* gameport address */
#define IDLE 0 /* state definitions for debouncer */
#define INPROG 1
#define WAITOPEN 2
void init_game(int),
clear_game(void),
debounce(void);
unsigned char get_press(void);
struct {
unsigned char seed;
unsigned char counter;
unsigned char new_value;
unsigned char last_value;
unsigned char state;
unsigned char key_down;
int multi;
} gamesw;
/*
** init_game(mode)
** call this routine before using any of the gameport support routines.
** Or, manually initialize the gamesw structure.
** "mode" is 1 to allow multiple keypresses, 0 for exclusion
*/
void init_game(int mode)
{
gamesw.seed = 100;
gamesw.multi = (unsigned char)(mode & 0xff);
clear_game();
}
/*
** clear_game()
** clears the game port structure items and allows for immediate
** re-processing of new keystrokes.
*/
void clear_game(void)
{
gamesw.key_down = gamesw.last_value = gamesw.new_value = 0;
gamesw.state = IDLE;
}
/*
** get_press()
** returns a fully debounced key value, or NUL if nothing
** pressed. Note that getting a waiting keystroke will re-init
** the control structure.
*/
unsigned char get_press(void)
{
unsigned char i;
if (gamesw.key_down == 0)
return(0);
i = gamesw.key_down;
gamesw.key_down = 0;
return(i);
}
/*
** debounce()
**
** This routine is called periodically (try for about 20 to 200 times per
** second, nominal) to process potential key presses. This system
** does NOT allow multiple key presses if the gamesw.multi byte is set
** to FALSE, and under those conditions will wait for a key to be
** fully debounced in order to return a value.
** If gamesw.multi is TRUE, then any stable value will be returned.
** In all cases, a pending keyvalue MUST be fetched via get_press or
** cleared via clear_game() before any further keypress is recognized.
** This routine returns nothing except through the gamesw structure.
*/
void debounce(void)
{
unsigned char i;
if (gamesw.key_down != 0)
return; /* do nothing until a key is read */
i = inp(GAMEPORT); /* read port, raw */
/* convert bits to high active, in lower nibble */
i = ~i;
i >>= 4;
gamesw.new_value = i & 0x0f;
switch (gamesw.new_value)
{
case 1:
case 2:
case 4:
case 8:
case 0:
break;
default: /* multiple keys down */
if (gamesw.multi)
break; /* multiple keys allowed */
gamesw.state = WAITOPEN; /* else wait for all open */
return;
}
if (gamesw.new_value != gamesw.last_value)
gamesw.state = IDLE;
switch (gamesw.state)
{
case IDLE:
if (gamesw.new_value == 0)
break;
/* save original keystroke */
gamesw.last_value = gamesw.new_value;
gamesw.counter = gamesw.seed;
gamesw.state = INPROG;
break;
case INPROG:
if (--gamesw.counter > 0)
break; /* not timed out yet */
gamesw.state = WAITOPEN;
gamesw.key_down = gamesw.new_value;
break;
case WAITOPEN:
if (gamesw.new_value != 0)
{ /* any closure restarts timeout */
gamesw.counter = gamesw.seed;
break;
}
if (--gamesw.counter > 0)
break;
gamesw.state = IDLE;
gamesw.last_value = gamesw.new_value = 0;
break;
default:
break;
}
}